/**
 * @file Demo.cpp
 * @author haiming
 * @brief 根据编译器版本走相应的测试函数，以测试单例模式线程安全的情况
 * 结论就是local static方式实现的单例模式不管是c++98还是c++11都符合线程安全
 * 两种测试指令
 * g++ -o demo Demo.cc LocalStatic.cpp -lpthread -std=c++98 -DDEBUG_LOCAL_STATIC
 * g++ -o demo Demo.cc LocalStatic.cpp -lpthread -std=c++11 -DDEBUG_LOCAL_STATIC
 * @version 0.1
 * @date 2022-08-05
 * 
 * @copyright Copyright (c) 2022
 * 
 */
#include "LocalStatic.h"
#include "Singleton.h"
#include <pthread.h>
#include <unistd.h>
#include <string.h>

using namespace std;


#ifdef DEBUG_SINGLETON
//测试懒汉单例模式
void* testsingleton(void* param)
{
    for (size_t i = 0; i < 10; i++)
    {
        Singleton* instance = Singleton::GetInstance();
        if (NULL == instance)
        {
            perror("instance is null!");
        }
        else
        {
            printf("instance address :%p\n", instance);
        }
        usleep(1000*10);
    }
}
//多线程测试懒汉单例模式，可以得出该模式不是线程安全的
void multhread()
{
    pthread_t tid;
    for (size_t i = 0; i < 10; i++)
    {
        int errcode = pthread_create(&tid, NULL, testsingleton, NULL);
        if (0 == errcode)
        {
            pthread_join(tid, nullptr);
        }
    }
}

int main(int argc, char** argv)
{
    printf("welcome to Singleton Demo!\n");
    printf("cplus version:%ld.\n", __cplusplus);
    multhread();
    return 0;
}

#elif DEBUG_LOCAL_STATIC
void* func(void* name)
{
	for(int i=0; i<10; i++)
	{
		LocalStatic* instance = LocalStatic::GetInstance();
		if(instance == NULL)
		{
			printf("instance is null\n");
		}
		else
		{
			printf("func instance address :%p\n", instance);
		}
		usleep(1000*10);
	}
    return NULL;
}
void* func1(void* name)
{
	for(int i=0; i<10; i++)
	{
		LocalStatic* instance = LocalStatic::GetInstance();
		if(instance == NULL)
		{
			printf("instance is null\n");
		}
		else
		{
			printf("func1 instance address :%p\n", instance);
		}
		usleep(1000*10);
	}
    return NULL;
}

//多线程测试饿汉单例模式
#if(__cplusplus > 199711L)
#include <thread>
void testcxx11()
{
    printf("%s\n", __FUNCTION__);
    // thread th(func, (void*)"func");
    // thread th1(func, (void*)"func1");
    // thread th2(func, (void*)"func2");

    thread th(func, nullptr);
    thread th1(func1, nullptr);
    th.join();
    th1.join();
}
#else
int testcxx98()
{
    printf("%s\n", __FUNCTION__);
    int errcode;
    pthread_t pid1, pid2, pid3;
    errcode = pthread_create(&pid1, NULL, func, NULL);
    if(errcode != 0)
    {
        printf("create thread error :%s\n", strerror(errcode));
        return -1;
    }

    errcode = pthread_create(&pid2, NULL, func1, NULL);
    if(errcode != 0)
    {
        printf("create thread error :%s\n", strerror(errcode));
        return -1;
    }

    // errcode = pthread_create(&pid3, NULL, func, (void*)"func2");
    // if(errcode != 0)
    // {
    //     printf("create thread error :%s\n", strerror(errcode));
    //     return -1;
    // }
    pthread_join(pid2, NULL);
    pthread_join(pid1, NULL);
    pthread_join(pid3, NULL);
}
#endif

int main()
{
    printf("welcome to Singleton Demo!\n");
    printf("cplus version:%ld.\n", __cplusplus);
    for (size_t i = 0; i < 10; i++)
    {
        #if(__cplusplus > 199711L)

        testcxx11();

        #else

        testcxx98();

        #endif
    }
    sleep(1);
}

#endif